﻿using System;
using System.Drawing;
using GeoSketch2.Core;
using System.Xml;
using System.IO;

namespace GeoSketch2.Archaeo
{
    /// <summary>
    /// A text to be displayed on the sketch
    /// </summary>
    public class InputText : BaseArchaeoDrawableObject
    {
        #region XMLElementsName
#pragma warning disable 1591
        public const string XML_Position = "Position";
        public const string XML_Text = "Text";
#pragma warning restore 1591
        #endregion

        #region Fields
        /// <summary>
        /// The text to be displayed
        /// </summary>
        public string Text;

        RectangleF TextBounds;

        BaseViewport Viewport;

        /// <summary>
        /// The position of the text
        /// </summary>
        public Point2D64D Position;
        #endregion

        #region Constructor
        /// <summary>
        /// A point with 2D coordinates
        /// </summary>
        /// <param name="Position">The location comment</param>
        /// <param name="Text">The text of the comment, can be different from the comment of the object itself</param>
        /// <param name="Layer">The layer of the point</param>
        /// <param name="ExcavationUnit">The excavation unit of the object</param>
        public InputText(Point2D64D Position, string Text, Layer Layer, ExcavationArea ExcavationArea)
            : this(Position, Text, Layer, ExcavationArea, ColorByLayer())
        {
        }

        /// <summary>
        /// A point with 2D coordinates
        /// </summary>
        /// <param name="Position">The location comment</param>
        /// <param name="Text">The text of the comment, can be different from the comment of the object itself</param>
        /// <param name="Layer">The layer of the point</param>
        /// <param name="Color">The color of the point</param>
        /// <param name="ExcavationUnit">The excavation unit of the object</param>
        public InputText(Point2D64D Position, string Text, Layer Layer, ExcavationArea ExcavationArea, Color Color)
            : this(Position, Text, Layer, ExcavationArea, Color, Text)
        {
        }

        /// <summary>
        /// A point with 2D coordinates
        /// </summary>
        /// <param name="Position">The location comment</param>
        /// <param name="Text">The text of the comment, can be different from the comment of the object itself</param>
        /// <param name="Layer">The layer of the point</param>
        /// <param name="Color">The color of the point</param>
        /// <param name="ExcavationUnit">The excavation unit of the object</param>
        /// <param name="Comment">The comment about of the point</param>
        public InputText(Point2D64D Position, string Text, Layer Layer, ExcavationArea ExcavationArea, Color Color, string Comment)
            : this(Position, Text, Layer, ExcavationArea, Color, Comment, DateTime.Now)
        {
        }

        /// <summary>
        /// A point with 2D coordinates
        /// </summary>
        /// <param name="Position">The location comment</param>
        /// <param name="Text">The text of the comment, can be different from the comment of the object itself</param>
        /// <param name="Layer">The layer of the point</param>
        /// <param name="Color">The color of the point</param>
        /// <param name="ExcavationUnit">The excavation unit of the object</param>
        /// <param name="Comment">The comment about of the point</param>
        /// <param name="CreationTime">The date of creation of the object</param>
        public InputText(Point2D64D Position, string Text, Layer Layer, ExcavationArea ExcavationArea, Color Color, string Comment, DateTime CreationTime)
            : base(Layer, Color, LineTypeByLayer(), ExcavationArea, Comment, CreationTime)
        {
            this.Position = Position;
            TextBounds = new RectangleF();
            this.Text = Text;
        }

        /// <summary>
        /// A point with 2D coordinates
        /// </summary>
        /// <param name="Xr">The XmlReader to read from</param>
        /// <param name="Site">The site of the object</param>
        public InputText(XmlReader Xr, ArchaeoProject Project)
            : base(Xr, Project)
        {
            TextBounds = new RectangleF();
            
            Xr.ReadToFollowing(XML_SpecificInfos);

            #region Position
            Xr.ReadToFollowing(XML_Position);
            Xr.ReadToFollowing(typeof(Point2D64D).FullName);
            this.Position = new Point2D64D(Xr);
            #endregion

            #region Text
            Xr.ReadToFollowing(XML_Text);
            this.Text= Xr.ReadString();
            #endregion

            Xr.ReadEndElement();

            Xr.ReadEndElement();
        }
        #endregion

        #region Methods
        /// <summary>
        /// The draw method for each object if selected
        /// </summary>
        /// <param name="Viewport">The viewport to draw to</param>
        protected override void DrawSelected(BaseViewport Viewport)
        {
            DrawCustomPen(Viewport, Core.Vars.Setup.Tools.TSelection.SelectionPen);
        }
        /// <summary>
        /// The draw method for each object if not selected
        /// </summary>
        /// <param name="Viewport">The viewport to draw to</param>
        protected override void DrawUnselected(BaseViewport Viewport)
        {
            DrawCustomPen(Viewport, Pen);
        }

        /// <summary>
        /// The draw method for each object with a custom pen
        /// </summary>
        /// <param name="Viewport">The viewport to draw to</param>
        /// <param name="CustomPen">The custom pen object to draw the object with</param>
        public override void DrawCustomPen(BaseViewport Viewport, Pen CustomPen)
        {
            this.Viewport = Viewport;

            Point2D64D Point_screen = Viewport.Object2ImageTransformation.Transform(Position);

            TextBounds.Size = Viewport.Graphic.MeasureString(Text, Vars.Setup.DrawableObjects.InputText.TextFont);
            TextBounds.X = (float)(Point_screen.X - TextBounds.Width / 2);
            TextBounds.Y = (float)(Point_screen.Y - TextBounds.Height / 2);

            Viewport.Graphic.DrawString(Text, Vars.Setup.DrawableObjects.InputText.TextFont, CustomPen.Brush, TextBounds.Location);
        }

        /// <summary>
        /// The method to test if an object is near to the point clicked, for an object selection purpose
        /// </summary>
        /// <param name="Clic">The point clicked in object coordinates</param>
        /// <param name="IsNearDistance">The distance under which the clic is near to the object</param>
        public override bool IsNear(Point2D64D Clic, double IsNearDistance)
        {
            Point2D64D ClicScreen = Viewport.Object2ImageTransformation.Transform(Clic);

            if (ClicScreen.X > TextBounds.X &&
                ClicScreen.X < TextBounds.X + TextBounds.Width &&
                ClicScreen.Y > TextBounds.Y &&
                ClicScreen.Y < TextBounds.Y + TextBounds.Height)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Clones the object
        /// </summary>
        public override T Clone<T>()
        {
            return (T)(object)new InputText(Position.DeepClone(), Text, Layer, ExcavationArea, Color, Comment);
        }

        /// <summary>
        /// Translates the object
        /// </summary>
        /// <param name="Vector">The translation vector</param>
        public override void Translate(Point2D64D Vector)
        {
            Position.X += Vector.X;
            Position.Y += Vector.Y;
        }

        /// <summary>
        /// Writes the object to a file
        /// </summary>
        /// <param name="Xw">The XmlWriter to write to</param>
        public override void ToFile(XmlWriter Xw)
        {
            Xw.WriteStartElement(this.GetType().FullName);

            #region Object Base Information
            this.BaseInfosToFile(Xw);
            #endregion

            #region Object Specific Information
            Xw.WriteStartElement(XML_SpecificInfos);

            #region Position
            Xw.WriteStartElement(XML_Position);
            Position.ToFile(Xw);
            Xw.WriteEndElement();
            #endregion

            #region Text
            Xw.WriteStartElement(XML_Text);
            Xw.WriteString(this.Text);
            Xw.WriteEndElement();
            #endregion

            Xw.WriteEndElement();
            #endregion

            Xw.WriteEndElement();
        }

        public override void ToDXFr13(TextWriter Tw)
        {
            Tw.WriteLine("0");
            Tw.WriteLine("TEXT");

            this.BaseInfosToDXFR13(Tw);

            FileIO.WriteDXFR13TextCenter(Tw, this.Position, this.Text, Vars.Setup.FileIO.DXFR13.DefaultTextHeight);
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the bounding box of the object, the Y-axis direction of the REctangleD must be upside
        /// </summary>
        public override RectangleD Bounds
        {
            get
            {
                return RectangleD.FromCenter(Position, TextBounds.Width, TextBounds.Height, YAxisDirection.UpSide);
            }
        }
        #endregion
    }
}
